// 文件名：basic_string_uri_builder.cpp
// 目的：构建 URL 查询字符串，包含对键/值的百分号编码（percent-encoding）。
// urlEncode：
//   - 保留字符：字母数字及 - _ . ~ 直接输出；
//   - 其它字节编码为 "%XX"（大写十六进制，两位宽度，前导 0）；
//   - 循环变量使用 unsigned char，避免 std::isalnum 的未定义行为（带符号 char 为负时出错）。
// buildQuery：
//   - 预分配近似容量，减少扩容；
//   - 以 '&' 连接多项，每项为 urlEncode(key) + '=' + urlEncode(value)。
// 复杂度：O(T)，T 为所有键值串长度之和。
// 注意：
//   - 此编码适用于 application/x-www-form-urlencoded 的基础需求，但未处理空格转 '+'（本实现空格会转 %20）；
//   - 若键/值来自不可信输入，拼接到 URL 中前应考虑大小与注入风险；
//   - 更完整的 URL 处理建议使用专业库（如 cpp-netlib、Boost.URL）。

#include <cctype>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <string_view>
#include <vector>

std::string urlEncode(std::string_view value) {
    std::ostringstream oss;
    oss << std::hex << std::uppercase;
    for (unsigned char c : value) {
        if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            oss << c;
        } else {
            oss << '%' << std::setw(2) << std::setfill('0')
                << static_cast<int>(c);
        }
    }
    return oss.str();
}

std::string buildQuery(const std::vector<std::pair<std::string, std::string>>& kv) {
    if (kv.empty()) return {};
    std::string query;
    query.reserve(kv.size() * 16);

    bool first = true;
    for (const auto& [key, value] : kv) {
        if (!first) {
            query.push_back('&');
        }
        first = false;
        query.append(urlEncode(key));
        query.push_back('=');
        query.append(urlEncode(value));
    }
    return query;
}

int main() {
    std::vector<std::pair<std::string, std::string>> params = {
        {"q", "c++ string uri"},
        {"page", "1"},
        {"lang", "zh-CN"},
    };
    std::string query = buildQuery(params);
    std::cout << "/search?" << query << '\n';
    return 0;
}